<?php
namespace core\modules;

use core\Func;
/**
 * 菜单配置类
 */
class Menu
{


  const TYPE_NONE="none";
  const TYPE_TITLE="title";
  const TYPE_LINE="line";
  const TYPE_GROUP="group";
  const TYPE_MENU="menu";
  const TYPE_OTHER="other";

  // 菜单数据
  protected $data=array();


	function checkAc($conf,$ac){
    $type=$conf["type"];
    if ($type==static::TYPE_MENU){
      $key=empty($conf["ac"])?(empty($conf["href"])?"":$conf["href"]):$conf["ac"];
      if (!$ac->check($key)){
          return "";
      }

    }

		return $conf;
	}

  // 根据配置模板生成菜单
	function getMenu($template,$ac){
    $template=Func::str2arr($template);
    $result=[];
		$last_type="";//记录上一次的type，用于取消连续的分界线

		foreach ($template as $key => $value) {

			// Menu.checkItem事件
			$conf=$this->checkAc($value,$ac);
			if (empty($conf)) continue;

			// 根据菜单类型进行处理

			$type=$conf["type"];

			switch ($type) {
	      case static::TYPE_NONE:
	        $last_type=static::TYPE_NONE;
	      break;
	      case static::TYPE_TITLE:
          if (!in_array($last_type,[static::TYPE_TITLE])){
            $result[]=$conf;
            $last_type=static::TYPE_TITLE;
          }
	      break;
	      case static::TYPE_LINE:
	        if (!in_array($last_type,[static::TYPE_LINE,static::TYPE_TITLE])){
						$result[]=$conf;
            $last_type=static::TYPE_LINE;
					}

	      break;
	      case static::TYPE_GROUP:
					$conf['children']=$this->getMenu($conf['children'],$ac);
					if (!empty($conf['children'])) $result[]=$conf;
	        $last_type=static::TYPE_GROUP;
	      break;
	      case static::TYPE_MENU:
					$result[]=$conf;
	        $last_type=static::TYPE_MENU;
	      break;
	      case static::TYPE_OTHER:
					$result[]=$conf;
	        $last_type=static::TYPE_OTHER;
	      break;
	      default:
	        throw new Exception("Menu type error: ".$name);
	      break;
			}

		}

		if (!empty($result)){

			// 清理第一个是分界线的情况
			reset($result);
			$first = current($result);
			if ($first["type"]==static::TYPE_LINE) array_shift($result);

			// 清理最后一个是分界线或者title的情况
			reset($result);
			$end = end($result);
			if ($end["type"]==static::TYPE_LINE) array_pop($result);
			if ($end["type"]==static::TYPE_TITLE) array_pop($result);

			reset($result);
		}



    return $result;
  }
	function makeMenu($menus){

		$htmls="";

		foreach ($menus as $conf) {

			$type=$conf["type"];

			switch ($type) {

	      case static::TYPE_TITLE:
	        $htmls.='<li class="nav-small-cap">'.$conf["title"].'</li>';
	      break;
	      case static::TYPE_LINE:
	        $htmls.='<li class="nav-devider"></li>';
	      break;
	      case static::TYPE_GROUP:
					$htmls2=$this->makeMenu($conf['children']);

					if (!empty($htmls2)){

						$icon=(empty($conf["icon"]))?"":'  <i class="'.$conf["icon"].'"></i>';
						$htmls.='<li><a class="has-arrow waves-effect waves-dark" href="#" aria-expanded="false">';
						$htmls.='  '.$icon.'<span class="hide-menu">'.$conf["title"].'</span></a>';
						$htmls.="<ul>".$htmls2."</ul></li>";
					}

	      break;
	      case static::TYPE_MENU:
					$target=(empty($conf["target"]))?"_self":$conf["target"];
					$icon=(empty($conf["icon"]))?"":'  <i class="'.$conf["icon"].'"></i>';
					$htmls.='<li><a data-id="'.$conf["href"].'" href="'.$conf["href"].'" target="'.$target.'">'.$icon.$conf["title"].'</a></li>';

	      break;
	      default:
	        throw new Exception("Menu type error: ".$name);
	      break;
			}

		}
		return $htmls;
	}
	function make($m,$ac){
		$menus=$this->getMenu($m,$ac);
		return $this->makeMenu($menus);
	}
  function first($m,$ac){
    $menu=$this->getMenu($m,$ac);
    return $this->getFirst($menu);
  }
  function getFirst($list){
    $result="";
		foreach ($list as $v) {
			if ($v["type"]==static::TYPE_MENU){
				$result=$v;
				break;
			}
			if (!empty($v["children"])){
				$result=$this->getFirst($v["children"]);
				if (!empty($result)){
					break;
				}
			}
		}

		return $result;
  }
  function __construct($option=array()){
    $this->clean();
    if (!empty($option)) $this->setOption($option);
  }
  // 通过配置数组初始化
  function setOption($option){
    $this->data=Func::array_merge_deep($this->data,$option);
		return $this;
  }
  // 清理，初始化为空菜单
  function clean(){
    $this->data=array(
      "id"=>"",
      "type"=>static::TYPE_NONE,
      "title"=>"",
      "ac"=>"",
      "hash"=>"",
      "href"=>"",
      "onclick"=>"",
      "target"=>"",
      "order"=>0,
      "icon"=>array(
        "el"=>"i",
        "class"=>"",
      ),
      "children"=>array(),


    );
		return $this;
  }
  // 获取所有配置
  function getData(){
    return $this->data;
  }
	// 添加子菜单
	function children($menuItem){
		if (!is_object($menuItem)){
			if (is_array($menuItem)){
				$menuItem=new self($menuItem);
			}else{
				throw new Exception("Menu Item Error: ".$key);
			}
		}

		$this->data["children"][]=$menuItem;
		return $this;
	}
  // 获取菜单单项配置
  function get($key,$defaultValue=""){
    $key=strtolower($key);
    $keys=Func::str2arr($key,".");
    $len=count($keys);
    $lastIndex=$len-1;
    $d=&$this->data;
    for ($i=0; $i < $len ; $i++) {
      $k=$keys[$i];
      if (isset($d[$k])){
        if ($i==$lastIndex){
          return $d[$k];
        }else{
          $d=&$d[$k];
        }
      }else{
        return $defaultValue;
      }

    }
    return $defaultValue;

  }
  // 设置菜单配置项
  function set($key,$value){
    $key=strtolower($key);
    $keys=Func::str2arr($key,".");
    $len=count($keys);
    $lastIndex=$len-1;
    $d=&$this->data;
    for ($i=0; $i < $len ; $i++) {
      $k=$keys[$i];
      if ($i==$lastIndex){
        $d[$k]=$value;
      }else{
        if (!isset($d[$k])){
          $d[$k]=array();
        }
        $d=&$d[$k];
      }
    }
		return $this;
  }
  //设置菜单类型
  function setType($name){
		if (empty($name)) $name="none";
    switch (strtolower(trim($name))){
      case static::TYPE_NONE:
        $this->data["type"]=static::TYPE_NONE;
      break;
      case static::TYPE_TITLE:
        $this->data["type"]=static::TYPE_TITLE;
      break;
      case static::TYPE_LINE:
        $this->data["type"]=static::TYPE_LINE;
      break;
      case static::TYPE_GROUP:
        $this->data["type"]=static::TYPE_GROUP;
      break;
      case static::TYPE_MENU:
        $this->data["type"]=static::TYPE_MENU;
      break;
      case static::TYPE_OTHER:
        $this->data["type"]=static::TYPE_OTHER;
      break;
      default:
        throw new Exception("Menu type error: ".$name);
      break;
    }
		return $this;
  }




}
